package cn.well.cloud.mutidatasource.config;

import cn.well.cloud.base.meta.MpFieldHandler;
import cn.well.cloud.base.warpper.factory.MapWrapperFactory;
import cn.well.cloud.mutidatasource.DynamicDataSource;
import cn.well.cloud.mutidatasource.Enum.DataSourceAddressEnum;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 默认多数据源配置
 * 
 * 2020年4月14日
 * @author wison
 *
 */
@Slf4j
@Configuration
public class DynamicDataSourceConfig {

    @Autowired
    private MybatisPlusConfig mybatisPlusConfig;

    @Value("${log.show}")
    private String show;

    /**
     * 配置master数据源
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.druid.master")
    public DataSource masterDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 配置slave数据源
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.druid.slave")
    public DataSource slaveDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    /**
     * 初始化路由DataSource
     */
    @Bean("myDataSource")
    @Primary
    public DataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource) {

        Map<Object, Object> targetDataSources = new HashMap<>(5);
        targetDataSources.put(DataSourceAddressEnum.MASTER, masterDataSource);
        targetDataSources.put(DataSourceAddressEnum.SLAVE, slaveDataSource);
        return  new DynamicDataSource(masterDataSource, targetDataSources);
    }

    @Bean
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(ObjectProvider<List<ConfigurationCustomizer>> mybatisConfigurationCustomizer) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
//        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{mybatisPlusConfig.paginationInterceptor()});
        sqlSessionFactoryBean.setDataSource(dataSource(masterDataSource(),slaveDataSource()));
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        //此处卡了很久，如果不配置此处，会出现plus中基础方法未绑定的异常
        //设置扫描的xml,相当于yml中的配置
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:cn/**/mapping/**/*.xml"));
        //设置扫描的实体包，相当于yml中的配置
        sqlSessionFactoryBean.setTypeAliasesPackage("cn.well.cloud.modular.system.model;cn.well.cloud.modular.model;cn.well.cloud.**.model;cn.well.cloud.modular.model");
        //全局配置
        GlobalConfig globalConfig  = new GlobalConfig();
        //配置填充器,多数据源时，仅扫描是无效的，需要手动配置handler
        globalConfig.setMetaObjectHandler(new MpFieldHandler());
        sqlSessionFactoryBean.setGlobalConfig(globalConfig);

        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBean.getObject();
        //下划线驼峰转换，作用于javabean的field的,并不是map，如果map想要驼峰，重写方法实现
        sqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);
        //map驼峰，重写方法实现，相当于GunsPropertiesConfig中的mybatisConfigurationCustomizer类
        sqlSessionFactory.getConfiguration().setObjectWrapperFactory(new MapWrapperFactory());


//        if("true".equalsIgnoreCase(show)) {
//            sqlSessionFactory.getConfiguration().setLogImpl(StdOutImpl.class);
//        }
        return sqlSessionFactory;
    }

}
